/* 
 * Copyright (c) 2010 Adam Markiewicz
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file containers/fixedarraytest.cpp
 * @author Adam Markiewicz
 */

#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>

#include <containers/fixedarray.h>
#include <containers/iterators.h>
#include <core/memory/newallocator.h>

#include <iostream>

using namespace Clea::Containers;
using namespace Clea::Core::Memory;

class FixedArrayTest : public CppUnit::TestFixture
{
    CPPUNIT_TEST_SUITE(FixedArrayTest);
    CPPUNIT_TEST(accessTest);
    CPPUNIT_TEST(copyTest);
    CPPUNIT_TEST(iteratorTest);
    CPPUNIT_TEST_SUITE_END();
    
public:
    void setUp();
    void tearDown();
    
protected:
    void accessTest();
    void copyTest();
    void iteratorTest();
};

class TestAllocator : public NewAllocator
{
};

void FixedArrayTest::setUp()
{
    CppUnit::TestFixture::setUp();
}

void FixedArrayTest::tearDown()
{
    CppUnit::TestFixture::tearDown();
}

void FixedArrayTest::accessTest()
{
    FixedArray<int, NewAllocator> array(5);
    
    for (int i = 0; i < array.size(); i++) {
        array[i] = i;
    }
}

void FixedArrayTest::copyTest()
{
    FixedArray<int, NewAllocator> array1(10);
    
    for (int i = 0; i < array1.size(); i++) {
        array1[i] = i;
    }
    
    FixedArray<int, NewAllocator> array2(array1);
    
    CPPUNIT_ASSERT(array1.size() == array2.size());
    
    for (int i = 0; i < array1.size(); i++) {
        CPPUNIT_ASSERT(array1[i] == array2[i]);
    }
}

void FixedArrayTest::iteratorTest()
{
    FixedArray<int> array(10);
    
    for (int i = 0; i < array.size(); i++) {
        array[i] = i;
    }
    
    ForwardIterator<FixedArray<int> > iter(array);
    
    for (int i = 0; i < array.size(); i++, iter++) {
        CPPUNIT_ASSERT(array[i] == *iter);
    }
    CPPUNIT_ASSERT(iter == false);
    
    iter.begin();
    CPPUNIT_ASSERT(*iter == 0);
    
    BackwardIterator<FixedArray<int> > biter(array);
    
    for (int i = 9; i >= 0; i--, biter--) {
        CPPUNIT_ASSERT(array[i] == *biter);
    }
    CPPUNIT_ASSERT(biter == false);
    
    biter.end();
    CPPUNIT_ASSERT(*biter == 9);
    
    BidirectionalIterator<FixedArray<int> > diter(array);
    int i = 0;
    while (diter) {
        CPPUNIT_ASSERT(i == *diter);
        diter++;
        i++;
    }
    
    ForwardIterator<FixedArray<int> > iter2(array);
    ForwardIterator<FixedArray<int> > iter3(array);
    
    CPPUNIT_ASSERT(iter2 == iter3);
    
    BidirectionalIterator<FixedArray<int> > diter2(array);
    BidirectionalIterator<FixedArray<int> > diter3(diter2);
    
    CPPUNIT_ASSERT(diter2 == diter3);
}

CPPUNIT_TEST_SUITE_REGISTRATION(FixedArrayTest);

int main (int argc, char* argv[])
{
    // informs test-listener about testresults
    CppUnit::TestResult testresult;
    
    // register listener for collecting the test-results
    CppUnit::TestResultCollector collectedresults;
    testresult.addListener(&collectedresults);
    
    // register listener for per-test progress output
    CppUnit::BriefTestProgressListener progress;
    testresult.addListener(&progress);
    
    // insert test-suite at test-runner by registry
    CppUnit::TestRunner testrunner;
    testrunner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
    testrunner.run(testresult);
    
    // output results in compiler-format
    CppUnit::CompilerOutputter compileroutputter(&collectedresults, std::cerr);
    compileroutputter.write();
    
    // return 0 if tests were successful
    return collectedresults.wasSuccessful() ? 0 : 1;
}